package com.aldobucchi.x.flash.geom
{


	import flash.display.DisplayObject;
	import flash.geom.Point;
	import flash.geom.Rectangle;



	public class RectangleWithRotation extends Rectangle
	{
		
		
		
		/**
		 * 
		 * Rotation in radians
		 * 
		*/		
		public var rotation:Number;

		
		public function RectangleWithRotation( x:Number=0, y:Number=0, width:Number=0, height:Number=0, rotation:Number=0 )
		{

			super( x, y, width, height );

			this.rotation = rotation;

		}
		
		
		
		override public function toString( ):String
		{
		
			return super.toString() + " " + rotation;
		
		}
		
		
		
		
		public function applyPropertiesTo( target:DisplayObject ):void
		{

			target.rotation 	= this.rotation;

			target.width 		= this.width;
			target.height 		= this.height;	

			target.x 			= this.x;
			target.y 			= this.y;

		}
		
		
		
		
		
		
		
		
		/**
		 * 
		 * Returns the transformation that should be applied to this rectangle to become
		 * the "target" rectangle
		 * 
		 * @param fromRect
		 * @return 
		 * 
		 */		
		public function getDifference( target:RectangleWithRotation ):Transformation2D
		{
			
			var scaleX:Number = target.width / this.width;
			var scaleY:Number = target.height / this.height;
			
			var rotationDegrees:Number = target.rotation - this.rotation;
			var rotationRadians:Number = GeomUtil.degreesToRadians( rotationDegrees );
			
			var dx:Number = target.x - this.x;
			var dy:Number = target.y - this.y;			
			
			
			return new Transformation2D( dx, dy, scaleX, scaleY, rotationRadians );
		
		}
		
		
		
		
		
		public static function fromRect( rect:Rectangle ):RectangleWithRotation
		{
			return new RectangleWithRotation( rect.x, rect.y, rect.width, rect.height, 0 );		
		}
		
		
		
		
		public static function getRect( target:DisplayObject, targetCoordinateSpace:DisplayObject ):RectangleWithRotation
		{
		

			// get a rectangle in the local coordinate space
			var rect:Rectangle = target.getRect( target );
			
			var topLeft:Point 			= rect.topLeft;
			var bottomRight:Point 		= rect.bottomRight;
			var topRight:Point			= new Point( bottomRight.x, topLeft.y );
			

			// Project the corners of the rectangle on the target coordinate space
			var newTopLeft:Point 		= PointUtil.lgl( topLeft, target, targetCoordinateSpace );
			var newBottomRight:Point 	= PointUtil.lgl( bottomRight, target, targetCoordinateSpace );
			var newTopRight:Point 		= PointUtil.lgl( topRight, target, targetCoordinateSpace );



			var newTopSide:Number 		= Point.distance( newTopLeft, newTopRight );		
			var newRightSide:Number 	= Point.distance( newTopRight, newBottomRight );	



			// calculate rotation
			var newRotation:int = GeomUtil.getTotalRotation( target, targetCoordinateSpace );
			

		
			// special case ( rotation = 0 )
			// we optimize further calculations	
			if ( newRotation == 0 )
			{
				return new RectangleWithRotation( newTopLeft.x, newTopLeft.y, newTopSide, newRightSide, 0 );
			}
			
			
			
			
			// TODO more special cases ( rotation = 90x )





			
			///// with three points and rotation we can build a rectangle
			
			
			// we find the lengths of two consecutive sides
			var topSide:Number 			= Point.distance( topLeft, topRight );		
			var rightSide:Number 		= Point.distance( topRight, bottomRight );		
			
			
	

			// we need to consider the case where the sides are inverted 
			// ( width/height ratio has changed because of rotation )
			var whr		:Number = topSide / rightSide;
			var nwhr	:Number = newTopSide / newRightSide;			
			
			
			var reverse:Boolean = false;
			
			if ( whr > 0 && nwhr < 0 )
				reverse = true;
			else if ( nwhr > 0 && whr < 0 )
				reverse = true;
			
			
			if ( reverse ) // swap sides
			{
				var t:Number = newTopSide;
				newTopSide = newRightSide;
				newRightSide = t;
			}
			
			
			// ready to construct the new rectangle

			return new RectangleWithRotation( newTopLeft.x, newTopLeft.y, newTopSide, newRightSide, newRotation );
		
		}

		
		
		
		
		
	}
	
}